/* Copyright 2011 Brian Cairns
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.wsnetwork.reforger;
import java.net.URL;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Character {
    Pattern STAT_PATTERN = Pattern.compile("\"(\\w+)\": (\\d+),");
    Pattern ITEM_PATTERN = Pattern.compile("/item/(\\d+)\\\" class=\\\"item\\\"");
    Pattern REFORGE_ADDITION_PATTERN =
        Pattern.compile("<span class=\"value\">\\+(\\d+)</span> <span class=\"name\">(\\w+)");
    Pattern REFORGE_REDUCTION_PATTERN =
        Pattern.compile("<span class=\"value\">(\\-\\d+)</span> <span class=\"name\">(\\w+)");

    private final Set<Integer> itemIds = new HashSet<Integer>();
    private final boolean isCombat;
    private final StatVector stats;
    private final StatVector reforgings;

    private static StatVector getStatVector(Matcher matcher) {
        Map<Stat, Integer> resultValues = new HashMap<Stat, Integer>();
        while (matcher.find()) {
            for (Stat stat : Stat.possibleStats) {
                if (stat.getBlizzardName().equals(matcher.group(1))) {
                    resultValues.put(stat, Integer.parseInt(matcher.group(2)));
                }
            }
        }
        return new StatVector(resultValues);
    }


    private static StatVector getReforgingVector(Matcher matcher) {
        Map<Stat, Integer> resultValues = new HashMap<Stat, Integer>();
        while (matcher.find()) {
            for (Stat stat : Stat.possibleStats) {
                if (stat.getName().equals(matcher.group(2))) {
                    resultValues.put(stat, Integer.parseInt(matcher.group(1)));
                }
            }
        }
        return new StatVector(resultValues);
    }

    public Character(String armoryUrl, URLRetriever urlRetriever) {
        try {
            String urlString = URLUTF8Encoder.encode(armoryUrl);
            URL url = new URL(urlString);
            String data = urlRetriever.getUrlContents(url);
            isCombat = (data.contains("class=\"spec tip\">Combat"));

            // Get item values
            Matcher itemMatcher = ITEM_PATTERN.matcher(data);
            while (itemMatcher.find()) {
                itemIds.add(Integer.parseInt(itemMatcher.group(1)));
            }

            // Get stat vector
            stats = getStatVector(STAT_PATTERN.matcher(data));

            // Get gem/enchant reforging vector
            StatVector increase = getReforgingVector(REFORGE_ADDITION_PATTERN.matcher(data));
            StatVector reduce = getReforgingVector(REFORGE_REDUCTION_PATTERN.matcher(data));
            reforgings = increase.add(reduce);
        } catch (Exception e) {
            throw new RuntimeException("Unable to load items from Armory URL: " + armoryUrl, e);
        }
    }

    public Collection<Integer> getItemIds() {
        return itemIds;
    }

    public boolean isCombat() {
        return isCombat;
    }

    public StatVector getStats() {
        return stats;
    }

    public StatVector getReforgings() {
        return reforgings;
    }
}